/**
  ******************************************************************************
  * File Name          : weight.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "bsp.h"
#include "spiflash.h"
#include "storage.h"
#include "tskcfg.h"
#include "route.h"
#include "network.h"

volatile Route_StorageDevlistType Route_StorageDevlist = {0};
#if(ROUTE_VERSION == 80)
static const char route_did_init[ROUTE_DID_BUFLEN] = "HZ80210315011";
#elif(ROUTE_VERSION == 70)
static const char route_did_init[ROUTE_DID_BUFLEN] = "HZ70210315011";
#elif (ROUTE_VERSION == 60)
static const char route_did_init[ROUTE_DID_BUFLEN] = "HZ60210315011";
#else
static const char route_did_init[ROUTE_DID_BUFLEN] = "HZ50210315011";
#endif

/* 刷新子设备列表 */
uint8_t Route_RefreshDeviceList(const char *did)
{
  Storage_SaveType sftype;
  
  memset((void *)&Route_StorageDevlist, 0, sizeof(Route_StorageDevlistType));
  
  if(did != NULL)
  {
    strncpy((char *)Route_StorageDevlist.dl.gw.did, did, ROUTE_DID_BUFLEN);
  }
  else
  {
    strncpy((char *)Route_StorageDevlist.dl.gw.did, ROUTE_SELF_DID, ROUTE_DID_BUFLEN);
  }
  
  Route_token((const char *)Route_StorageDevlist.dl.gw.did, (char *)Route_StorageDevlist.dl.gw.token, ROUTE_TOKEN_BUFLEN);
  
  strncpy((char *)Route_StorageDevlist.dl.hk.did, (const char *)Route_StorageDevlist.dl.gw.did, ROUTE_DID_BUFLEN);
  Route_StorageDevlist.dl.hk.did[0] = 'H';
  Route_StorageDevlist.dl.hk.did[1] = 'K';
  Route_token((const char *)Route_StorageDevlist.dl.hk.did, (char *)Route_StorageDevlist.dl.hk.token, ROUTE_TOKEN_BUFLEN);
  
#if((ROUTE_VERSION == 60) || (ROUTE_VERSION == 80))
  strncpy((char *)Route_StorageDevlist.dl.dk[0].did, (const char *)Route_StorageDevlist.dl.gw.did, ROUTE_DID_BUFLEN);
  Route_StorageDevlist.dl.dk[0].did[0] = 'D';
  Route_StorageDevlist.dl.dk[0].did[1] = 'K';
  Route_token((const char *)Route_StorageDevlist.dl.dk[0].did, (char *)Route_StorageDevlist.dl.dk[0].token, ROUTE_TOKEN_BUFLEN);
#endif

  vTaskSuspend(xRoute_485_Thd);  /* 挂起485任务 */
  
  uint8_t i,j;
  Route_PayloadType *proute = NULL;
  
  proute = pvPortMalloc(sizeof(Route_PayloadType));
  if(proute == NULL)
  {
    goto funout;
  }
  
  proute->trans_dir = ROUTE_TRSDIR_LOCAL_TO_SUBDEV,
  proute->pl_type   = ROUTE_PLTYP_UN_PING,
  proute->pl_len    = 0;

/* 查找 料线 子设备 */
  proute->dev_type  = RT_DV_LX;
  for(i=0; i<ROUTE_DEVICE_MAXNUM; i++)
  {
    proute->dev_addr = idx2add(i);
    
    for(j=0; j<3; j++)
    {
      xQueueReset(Route_485RxLink_Qhd);
      RS485_LinkSend(proute);
      
      if(xQueueReceive(Route_485RxLink_Qhd, &Route_485_rx_link_bck, 150) == pdTRUE)
      {
        if((Route_485_rx_link_bck.dev_addr == proute->dev_addr) && \
           (Route_PayloadCRC(&Route_485_rx_link_bck, ROUTE_PLCRC_CHECK) == 0) && \
           (Route_485_rx_link_bck.pl_type == ROUTE_PLTYP_UN_RESPING))
        {
          strncpy((char *)Route_StorageDevlist.dl.lx[i].did, (const char *)Route_StorageDevlist.dl.gw.did, ROUTE_DID_BUFLEN);
          Route_StorageDevlist.dl.lx[i].did[0] = 'L';
          Route_StorageDevlist.dl.lx[i].did[1] = 'X';
          if(i < 10)
          {
            Route_StorageDevlist.dl.lx[i].did[3] = i+'0';
          }
          else if((i>9)&&(i<16))
          {
            Route_StorageDevlist.dl.lx[i].did[3] = (i-10)+'A';
          }
          Route_token((const char *)Route_StorageDevlist.dl.lx[i].did, (char *)Route_StorageDevlist.dl.lx[i].token, ROUTE_TOKEN_BUFLEN);
          break;
        }
      }
    }
  }
  
/* 查找 除粪 子设备 */  
  proute->dev_type  = RT_DV_CF;
  for(i=0; i<ROUTE_DEVICE_MAXNUM; i++)
  {
    proute->dev_addr = idx2add(i);
    
    for(j=0; j<3; j++)
    {
      xQueueReset(Route_485RxLink_Qhd);
      RS485_LinkSend(proute);
      
      if(xQueueReceive(Route_485RxLink_Qhd, &Route_485_rx_link_bck, 150) == pdTRUE)
      {
        if((Route_485_rx_link_bck.dev_addr == proute->dev_addr) && \
           (Route_PayloadCRC(&Route_485_rx_link_bck, ROUTE_PLCRC_CHECK) == 0) && \
           (Route_485_rx_link_bck.pl_type == ROUTE_PLTYP_UN_RESPING))
        {
          strncpy((char *)Route_StorageDevlist.dl.cf[i].did, (const char *)Route_StorageDevlist.dl.gw.did, ROUTE_DID_BUFLEN);
          Route_StorageDevlist.dl.cf[i].did[0] = 'C';
          Route_StorageDevlist.dl.cf[i].did[1] = 'F';
          if(i < 10)
          {
            Route_StorageDevlist.dl.cf[i].did[3] = i+'0';
          }
          else if((i>9)&&(i<16))
          {
            Route_StorageDevlist.dl.cf[i].did[3] = (i-10)+'A';
          }
          Route_token((const char *)Route_StorageDevlist.dl.cf[i].did, (char *)Route_StorageDevlist.dl.cf[i].token, ROUTE_TOKEN_BUFLEN);
          break;
        }
      }
    }
  }

/* 查找 小窗 子设备 */  
  proute->dev_type  = RT_DV_XC;
  for(i=0; i<ROUTE_DEVICE_MAXNUM; i++)
  {
    proute->dev_addr = idx2add(i);
    
    for(j=0; j<3; j++)
    {
      xQueueReset(Route_485RxLink_Qhd);
      RS485_LinkSend(proute);
      
      if(xQueueReceive(Route_485RxLink_Qhd, &Route_485_rx_link_bck, 150) == pdTRUE)
      {
        if((Route_485_rx_link_bck.dev_addr == proute->dev_addr) && \
           (Route_PayloadCRC(&Route_485_rx_link_bck, ROUTE_PLCRC_CHECK) == 0) && \
           (Route_485_rx_link_bck.pl_type == ROUTE_PLTYP_UN_RESPING))
        {
          strncpy((char *)Route_StorageDevlist.dl.xc[i].did, (const char *)Route_StorageDevlist.dl.gw.did, ROUTE_DID_BUFLEN);
          Route_StorageDevlist.dl.xc[i].did[0] = 'X';
          Route_StorageDevlist.dl.xc[i].did[1] = 'C';
          if(i < 10)
          {
            Route_StorageDevlist.dl.xc[i].did[3] = i+'0';
          }
          else if((i>9)&&(i<16))
          {
            Route_StorageDevlist.dl.xc[i].did[3] = (i-10)+'A';
          }
          Route_token((const char *)Route_StorageDevlist.dl.xc[i].did, (char *)Route_StorageDevlist.dl.xc[i].token, ROUTE_TOKEN_BUFLEN);
          break;
        }
      }
    }
  }
  
  vPortFree(proute);
  
  vTaskResume(xRoute_485_Thd);
  
funout:

  Route_StorageDevlist.crc = crc16((uint8_t *)&Route_StorageDevlist.dl, sizeof(Route_DeviceListType));
	
	if(Storage_qhd != NULL)
	{
		sftype = SFLASH_SAVE_ROUTEPARA;
		xQueueSend(Storage_qhd, &sftype, 1000);
	}
  
  return 0;
}

uint8_t Route_IsDidMatchDevice(const char *did, uint8_t *devindex)
{
	Route_DidFormatType didst = {0};
  const Route_DeviceType *pdev = NULL;
  
	if(Route_ParseDID(did, &didst) != 0)
	{
		return 1;
	}
	
  pdev = Route_GetIndexInDevlist(didst.type, didst.devindex);
  if(pdev == NULL)
  {
    return 2;
  } 
		
  if(strcmp(did, (const char *)pdev->did) == 0)
  {
		if(devindex != NULL)
		{
			*devindex = didst.devindex;
		}
    return 0;
  }
	
	return 3;
}

void Route_IsTopoMatchDevice(void)
{
	uint8_t i, j;
	uint8_t match;
	
	memset(&Route_BoundList,   0, sizeof(Route_TopoSyncListType));
	memset(&Route_UnboundList, 0, sizeof(Route_TopoSyncListType));
	
  Route_ConvertToTopolist(&Route_LocalTopoList);
  
	Route_UnboundList.num = 0;  /* 多此一举的冗余 */
	
	for(i=0; i<Route_NetTopoList.topo_num; i++)
	{
		match = 0;
		
		for(j=0; j<Route_LocalTopoList.topo_num; j++)
		{
			if(strcmp(Route_NetTopoList.dids[i], Route_LocalTopoList.dids[j]) == 0)
			{
				match = 1;
				break;
			}
		}
		
		if(match == 0)
		{
			/* 未匹配, 拓扑表有,设备列表无,需要解绑 */
			strncpy(Route_UnboundList.item[Route_UnboundList.num].did, Route_NetTopoList.dids[i], ROUTE_DID_BUFLEN);
			Route_UnboundList.num += 1;
		}
	}
	
	
	Route_BoundList.num = 0;  /* 多此一举的冗余 */
	
	for(i=0; i<Route_LocalTopoList.topo_num; i++)
	{
		match = 0;
		
		for(j=0; j<Route_NetTopoList.topo_num; j++)
		{
			if(strcmp(Route_LocalTopoList.dids[i], Route_NetTopoList.dids[j]) == 0)
			{
				match = 1;
				break;
			}
		}
		
		if(match == 0)
		{
			/* 未匹配, 设备列表有,拓扑表无,需要绑定 */
			strncpy(Route_BoundList.item[Route_BoundList.num].did, Route_LocalTopoList.dids[i], ROUTE_DID_BUFLEN);
			Route_BoundList.num += 1;
		}
	}
	
	for(i=0; i<Route_BoundList.num; i++)
	{
		Route_token(Route_BoundList.item[i].did, Route_BoundList.item[i].token, ROUTE_TOKEN_BUFLEN);
	}
	
	for(i=0; i<Route_UnboundList.num; i++)
	{
		Route_token(Route_UnboundList.item[i].did, Route_UnboundList.item[i].token, ROUTE_TOKEN_BUFLEN);
	}
}

const Route_DeviceType *Route_GetIndexInDevlist(Route_DevType_Type type, uint8_t index)
{
  switch(type)
  {
    case RT_DV_UN:
    case RT_DV_ZL:
    case RT_DV_SP:
    case RT_DV_SW:
    case RT_DV_SD:
      return NULL;
    
    case RT_DV_GW:
      return (&(Route_DeviceList.gw));
    
    case RT_DV_HK:
      return (&(Route_DeviceList.hk));
    
    case RT_DV_XC:
      return (&(Route_DeviceList.xc[index]));
    
    case RT_DV_LX:
      return (&(Route_DeviceList.lx[index]));

    case RT_DV_CF:
      return (&(Route_DeviceList.cf[index]));
    
    case RT_DV_DK:
      return (&(Route_DeviceList.dk[index]));
    
    default:
      return NULL;
  }
  
}

void Route_ConvertToTopolist(Route_ToPoListType *local)
{
  uint8_t i, j;
  
  strncpy(local->dids[0], Route_DeviceList.hk.did, ROUTE_DID_BUFLEN);
  
  i=1;
  
  for(j=0; (i<ROUTE_GET_TOPO_MAXNUM) && (j<ROUTE_DEVICE_MAXNUM); j++)
  {
    if(Route_DeviceList.xc[j].did[0] != 0)
    {
      strncpy(local->dids[i++], Route_DeviceList.xc[j].did, ROUTE_DID_BUFLEN);
    }
  }
  
  for(j=0; (i<ROUTE_GET_TOPO_MAXNUM) && (j<ROUTE_DEVICE_MAXNUM); j++)
  {
    if(Route_DeviceList.lx[j].did[0] != 0)
    {
      strncpy(local->dids[i++], Route_DeviceList.lx[j].did, ROUTE_DID_BUFLEN);
    }
  }
  
  for(j=0; (i<ROUTE_GET_TOPO_MAXNUM) && (j<ROUTE_DEVICE_MAXNUM); j++)
  {
    if(Route_DeviceList.dk[j].did[0] != 0)
    {
      strncpy(local->dids[i++], Route_DeviceList.dk[j].did, ROUTE_DID_BUFLEN);
    }
  }
  
  for(j=0; (i<ROUTE_GET_TOPO_MAXNUM) && (j<ROUTE_DEVICE_MAXNUM); j++)
  {
    if(Route_DeviceList.cf[j].did[0] != 0)
    {
      strncpy(local->dids[i++], Route_DeviceList.cf[j].did, ROUTE_DID_BUFLEN);
    }
  }
  
  local->topo_num = i;
}

void Route_SaveDevlist(void)
{
  if(memcmp(ROUTE_FLASH_DEVICE_LIST, (const void*)&Route_StorageDevlist, sizeof(Route_StorageDevlistType)) != 0)
  {
    vTaskSuspendAll();
    
    fmc_write_8bit_data(CFLASH_DEVLIST_ADDR, sizeof(Route_StorageDevlistType), (uint8_t *)&Route_StorageDevlist);
    
    (void)xTaskResumeAll();
  }
}

uint8_t Route_CheckDevlist(void)
{
  if(Route_ParseDID(ROUTE_SELF_DID, NULL) != 0)
  {
    printf("devlist did err!\r\n");
    Route_RefreshDeviceList(route_did_init);
    return 1;
  }
  
  if(crc16((uint8_t *)&Route_DeviceList, sizeof(Route_DeviceListType)) != ROUTE_FLASH_DEVICE_LIST->crc)
  {
    printf("devlist crc err!\r\n");
    Route_RefreshDeviceList(route_did_init);
    return 2;
  }

  printf("Device list OK:%s\r\n", ROUTE_SELF_DID);
  
  return 0;
}
